package yb.ecp.fast.user.service;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Strings;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.security.CryptoUtil;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.Ref;
import yb.ecp.fast.infra.util.StringUtil;
import yb.ecp.fast.oplog.entity.OpLog;
import yb.ecp.fast.oplog.service.OpLogServiceImpl;
import yb.ecp.fast.user.dao.entity.ProfileDO;
import yb.ecp.fast.user.dao.mapper.ProfileMapper;
import yb.ecp.fast.user.dao.mapper.RoleMapper;
import yb.ecp.fast.user.exception.AuthException;
import yb.ecp.fast.user.infra.AuthConstant;
import yb.ecp.fast.user.infra.ErrorCode;
import yb.ecp.fast.user.infra.JsonUtil;
import yb.ecp.fast.user.manager.UserContextManager;
import yb.ecp.fast.user.service.VO.AccountPwdVO;
import yb.ecp.fast.user.service.VO.AccountVO;
import yb.ecp.fast.user.service.VO.DepartmentVO;
import yb.ecp.fast.user.service.VO.JobDTO;
import yb.ecp.fast.user.service.VO.LockVO;
import yb.ecp.fast.user.service.VO.ProfileConditionVO;
import yb.ecp.fast.user.service.VO.ProfileVO;
import yb.ecp.fast.user.service.VO.RegMemberVO;
import yb.ecp.fast.user.service.VO.RoleVO;
import yb.ecp.fast.user.service.VO.TechnicianVO;
import yb.ecp.fast.user.service.VO.UserCacheVO;
import yb.ecp.fast.user.service.VO.UserScore;
import yb.ecp.fast.user.service.VO.UserScoreVO;
import yb.ecp.fast.user.service.VO.UserVO;
import yb.ecp.fast.user.service.VO.WorkspaceVO;
import yb.ecp.fast.user.service.base.BaseService;
import yb.ecp.fast.user.util.BeanUtil;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * Created by LiChangjiang on 2017/12/27 0027.
 */
@RefreshScope
@Service
public class ProfileService extends BaseService<ProfileVO, ProfileDO> {
    private static final String COMM_ORDER_BY = "create_date desc,id desc";
    @Autowired
    ProfileMapper profileMapper;

    @Autowired
    AccountService accountService;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    ScepterService scepterService;

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    DepartmentService departmentService;

    @Autowired
    WorkspaceService workspaceService;

    @Autowired
    private UserContextManager userContextManager;

    @Autowired
    private OpLogServiceImpl opLogService;

    /**
     * 默认admin管理员id
     */
    @Value("${role.admin.roleId}")
    private String roleAdminId;

    @Value("${role.admin.password:SgcX!515}")
    private String defaultPassword;


    public void init() {
        super.addMapper(profileMapper);
    }

    public ProfileService() {
        super(ProfileVO.class, ProfileDO.class);
    }

    /**
     * 根据ids 查询用户列表
     */
    public List<UserVO> listByIds(List<String> ids) {
        init();

        PageHelperPlus.orderBy(COMM_ORDER_BY);
        List<ProfileDO> doList = profileMapper.selectByIds(ids);
        List<ProfileVO> voList = getVOList(doList);

        List<UserVO> userVOs = new ArrayList<>();

        for (ProfileVO profileVO : voList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }

        return userVOs;
    }

    /**
     * 查询用户列表, 排除操作人自己 (不分页)
     */
    public List<UserVO> list(ProfileConditionVO condtion, String userId) {
        init();
        String spaceId = userContextManager.getWorkspaceId(userId);
        condtion.setSpaceId(spaceId);
        condtion.setMyself(userId);
        if (!StringUtil.isNullOrSpace(condtion.getName())) {
            condtion.setName(condtion.getName().trim().replaceAll(" +", "%"));//将用户名中多个空格替换为%，模糊查询
        }

        PageHelperPlus.orderBy(COMM_ORDER_BY);
        List<ProfileDO> doList = profileMapper.list(condtion);
        List<ProfileVO> voList = getVOList(doList);

        List<UserVO> userVOs = new ArrayList<>();

        for (ProfileVO profileVO : voList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }

        return userVOs;
    }

    /**
     * 查询用户列表, 排除操作人自己
     *
     * @param condtion SearchCommonVO<ProfileVO>
     * @return PageCommonVO
     */
    public PageCommonVO<UserVO> list(SearchCommonVO<ProfileConditionVO> condtion, String userId) {
        init();
        String spaceId = userContextManager.getWorkspaceId(userId);

        condtion.getFilters().setSpaceId(spaceId);

        condtion.getFilters().setMyself(userId);

        ProfileConditionVO temp = condtion.getFilters();
        if (!StringUtil.isNullOrSpace(temp.getName())) {
            temp.setName(temp.getName().trim().replaceAll(" +", "%"));//将用户名中多个空格替换为%，模糊查询
            condtion.setFilters(temp);
        }

        PageCommonVO<ProfileVO> pageCommonVO = pageList(condtion);
        PageCommonVO<UserVO> r = BeanUtil.do2bo(pageCommonVO, PageCommonVO.class);
        List<ProfileVO> profileVOList = pageCommonVO.getPageInfoList();
        List<UserVO> userVOs = new ArrayList<>();
        for (ProfileVO profileVO : profileVOList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }
        r.setPageInfoList(userVOs);
        return r;
    }

    /**
     * 查询用户列表, 不排除操作人自己
     *
     * @param condtion SearchCommonVO<ProfileVO>
     * @return PageCommonVO
     */
    public PageCommonVO<UserVO> listProfiles(SearchCommonVO<ProfileConditionVO> condtion, String userId) {
        init();
        String spaceId = userContextManager.getWorkspaceId(userId);
        condtion.getFilters().setSpaceId(spaceId);
        ProfileConditionVO temp = condtion.getFilters();
        if (!StringUtil.isNullOrSpace(temp.getName())) {
            temp.setName(temp.getName().trim().replaceAll(" +", "%"));//将用户名中多个空格替换为%，模糊查询
            condtion.setFilters(temp);
        }
        PageCommonVO<ProfileVO> pageCommonVO = pageList(condtion);
        PageCommonVO<UserVO> r = BeanUtil.do2bo(pageCommonVO, PageCommonVO.class);
        List<ProfileVO> profileVOList = pageCommonVO.getPageInfoList();
        List<UserVO> userVOs = new ArrayList<>();
        for (ProfileVO profileVO : profileVOList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }
        r.setPageInfoList(userVOs);
        return r;
    }

    private PageCommonVO<ProfileVO> pageList(SearchCommonVO<ProfileConditionVO> condition) {
        PageCommonVO<ProfileVO> pageCommonVO = new PageCommonVO<>();
        PageHelperPlus.orderBy(COMM_ORDER_BY);
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<ProfileDO> doList = profileMapper.list(condition.getFilters());
        List<ProfileVO> voList = getVOList(doList);
        pageCommonVO.setPageInfo(new PageInfo<ProfileDO>(doList));
        pageCommonVO.setPageInfoList(voList);
        return pageCommonVO;
    }

    /**
     * 查询平台所有工作空间的用户，
     *
     * @param condtion SearchCommonVO<ProfileVO>
     * @param userId   String
     * @return PageCommonVO
     */
    public PageCommonVO<UserVO> listAll(SearchCommonVO<ProfileVO> condtion, String userId) {
        init();
        condtion.getFilters().setMyself(userId);
        ProfileVO temp = condtion.getFilters();
        if (!StringUtil.isNullOrSpace(temp.getName())) {
            temp.setName(temp.getName().trim().replaceAll(" +", "%"));//将用户名中多个空格替换为%，模糊查询
            condtion.setFilters(temp);
        }
        PageCommonVO<ProfileVO> pageCommonVO = super.list(condtion);
        PageCommonVO<UserVO> r = BeanUtil.do2bo(pageCommonVO, PageCommonVO.class);
        List<ProfileVO> profileVOList = pageCommonVO.getPageInfoList();

        List<UserVO> userVOs = new ArrayList<>();

        for (ProfileVO profileVO : profileVOList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }
        r.setPageInfoList(userVOs);
        return r;
    }

    /**
     * 查询工作空间的用户列表
     *
     * @param condtion SearchCommonVO<ProfileVO>
     * @return PageCommonVO
     */
    public PageCommonVO<UserVO> listByWorkspace(SearchCommonVO<ProfileVO> condtion) {
        init();

        ProfileVO temp = condtion.getFilters();
        if (!StringUtil.isNullOrSpace(temp.getName())) {
            temp.setName(temp.getName().trim().replaceAll(" +", "%"));
            condtion.setFilters(temp);
        }

        PageCommonVO<ProfileVO> pageCommonVO = new PageCommonVO<>();
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condtion.getPageNum(), condtion.getPageSize());
        List<ProfileDO> doList = profileMapper.listByRole(condtion.getFilters());
        List<ProfileVO> voList = getVOList(doList);
        pageCommonVO.setPageInfo(new PageInfo<ProfileDO>(doList));
        pageCommonVO.setPageInfoList(voList);
        List<ProfileVO> profileVOList = voList;
        PageCommonVO<UserVO> r = BeanUtil.do2bo(pageCommonVO, PageCommonVO.class);
        List<UserVO> userVOs = new ArrayList<>();

        for (ProfileVO profileVO : profileVOList) {
            UserVO user = packageUserInfo(profileVO);
            userVOs.add(user);
        }
        r.setPageInfoList(userVOs);
        return r;
    }


    /**
     * 查询详情
     *
     * @param id String
     * @return ProfileVO
     */
    @Override
    public UserVO item(String id) {
        ProfileVO profileVO = new ProfileVO();
        ProfileDO profileDO = profileMapper.selectById(id);

        if (null == profileDO) {
            LogHelper.error("用户信息不存在", -1);
            return null;
        }

        BeanUtils.copyProperties(profileDO, profileVO);

        UserVO userVO = packageUserInfo(profileVO);

        return userVO;
    }

    private ErrorCode checkAddProfile(ProfileVO profileVO) {
        ErrorCode checkCode = accountService.checkExistAccountName(profileVO.getLoginName());
        if (checkCode.getCode() == ErrorCode.Success.getCode()) {
            checkCode = checkExistMobile(profileVO.getMobile(), null);
        }
        return checkCode;
    }

    /**
     * 增加用户
     *
     * @param profileVO ProfileVO
     * @param userIdRef Ref<String>
     * @return ErrorCode
     * @throws Exception Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode insert(ProfileVO profileVO, Ref<String> userIdRef) throws Exception {
        check400Code(profileVO);
        ErrorCode checkCode = checkAddProfile(profileVO);
        if (checkCode.getCode() != ErrorCode.Success.getCode()) {
            return checkCode;
        }
        String userId = fastGenClient.textGuid().getValue();
        ProfileDO profileDO = new ProfileDO();
        profileVO.setUserId(userId);
        profileVO.setType(0);
        if (StringUtil.isNullOrEmpty(profileVO.getPassword())) {
            LogHelper.debug("账户密码为空，使用默认密码！");
            profileVO.setPassword(defaultPassword);
        }

        //添加用户名账号
        AccountPwdVO accountPwdVO = new AccountPwdVO();
        BeanUtils.copyProperties(profileVO, accountPwdVO);
        ErrorCode code = accountService.addAccountPwd(accountPwdVO);
        if (ErrorCode.Success != code) {
            return code;
        }

        //添加用户信息
        BeanUtils.copyProperties(profileVO, profileDO);
        profileDO.setSpaceId(profileVO.getSpaceId());
        if (null == profileDO.getLocked()) {
            profileDO.setLocked(0);
        }
        if (StringUtil.isNullOrSpace(profileDO.getDeptId())) {
            profileDO.setDeptId(AuthConstant.DEFAULT_PARENT_DEPT_ID);
        }

        int ret = profileMapper.insert(profileDO);
        if (!StringUtils.isBlank(profileDO.getJobId())) {
            String jobId = profileMapper.getJobById(profileDO.getJobId());
            if (!StringUtil.isNullOrEmpty(jobId)) {
                DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date();
                String format = formatter.format(date);
                String jobUserId = profileMapper.getJobUserById(profileVO.getUserId(), 1);
                if (!StringUtil.isNullOrEmpty(jobUserId)) {
                    profileMapper.updateJobUser(jobId, profileVO.getUserId(), format);
                } else {
                    String id = String.valueOf(snowflake());
                    profileMapper.createJobUser(id, jobId, profileVO.getUserId(), 1, format);
                }
            } else {
                return ErrorCode.JOBNULL;
            }
        }
        if (0 >= ret) {
            LogHelper.error("添加用户信息步骤异常！", ErrorCode.FailedToInsertRecord.getCode());
            return ErrorCode.FailedToInsertRecord;
        }

        List<String> roleIds = profileVO.getRoleIds();

        if (ListUtil.isNullOrEmpty(roleIds)) {
            userIdRef.set(userId);
            LogHelper.debug("用户没有设置角色信息！");
            return ErrorCode.Success;
        }

        addUserRoleRelation(roleIds, userId);

        userIdRef.set(userId);
        return ErrorCode.Success;
    }


    private void addUserRoleRelation(List<String> roleIds, String userId) {
        for (int i = 0; i < roleIds.size(); i++) {
            int roleFlag = 0;
            if (i == 0) {
                roleFlag = 1;
            }
            scepterService.setRoleUser(roleIds.get(i), userId, roleFlag);
        }
    }

    /**
     * 删除用户
     *
     * @param ids 批量删除的ID
     * @return ErrorCode
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode removeByIds(List<String> ids) {
        ErrorCode checkRet = checkRemoveCondition(ids);
        if (checkRet != ErrorCode.Success) {
            return checkRet;
        }

        for (String id : ids) {
            profileMapper.removeById(id);

            roleMapper.removeRoleByUser(id);

            accountService.removeAccountByUserId(id);
        }
        return ErrorCode.Success;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode removeSelfById(String id) {
        ErrorCode checkRet = checkRemoveCondition(Collections.singletonList(id));
        if (checkRet != ErrorCode.Success) {
            return checkRet;
        }
        UserVO m = item(id);
        saveOpLog(m, id);
        profileMapper.removeById(id);
        roleMapper.removeRoleByUser(id);
        accountService.removeAccountByUserId(id);
        return ErrorCode.Success;
    }

    private void saveOpLog(UserVO m, String userId) {
        if (null == userId) {
            throw new AuthException("当前操作人信息获取失败");
        }
        OpLog l = OpLog.builder().method("yb.ecp.fast.user.service.ProfileService.removeSelfById")
                .msgJson(JsonUtil.objectToString(m))
                .searchId(m.getLoginName())
                .updatedTime(new Date())
                .userId(userId)
                .userName(m.getName())
                .orgId(m.getSpaceId())
                .build();
        opLogService.saveOpLog(l);
    }

    /**
     * 校验删除操作条件是否满足
     *
     * @param ids List<String>
     * @return ErrorCode
     */
    private ErrorCode checkRemoveCondition(List<String> ids) {
        for (String userId : ids) {
            //查询角色信息（用于展示）
            List<String> roleVOIds = scepterService.getRoleIdsByUserId(userId);

            if (roleVOIds.contains(roleAdminId)) {
                return ErrorCode.AdminCannotRemove;
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 修改用户信息
     *
     * @param profileVO ProfileVO
     * @return ErrorCode
     */
    @Override
    public ErrorCode update(ProfileVO profileVO) {
        check400Code(profileVO);
        ErrorCode checkCode = checkExistMobile(profileVO.getMobile(), profileVO.getUserId());

        if (checkCode.getCode() != ErrorCode.Success.getCode()) {
            return checkCode;
        }

        ProfileDO profileDO = new ProfileDO();

        BeanUtils.copyProperties(profileVO, profileDO);

        int ret = profileMapper.update(profileDO);
        if (0 >= ret) {
            LogHelper.error("修改用户信息步骤失败！", ErrorCode.FailedToUpdateRecord.getCode());
            return ErrorCode.FailedToUpdateRecord;
        }

        if (!StringUtil.isNullOrSpace(profileVO.getSpaceId())) {
            //移除角色信息
            roleMapper.removeRoleByUser(profileVO.getUserId());
        }

        List<String> roleIds = profileVO.getRoleIds();
        if (!ListUtil.isNullOrEmpty(roleIds)) {
            //移除角色信息
            roleMapper.removeRoleByUser(profileVO.getUserId());

            addUserRoleRelation(roleIds, profileVO.getUserId());
        }
        return ErrorCode.Success;
    }

    private void check400Code(ProfileVO vo) {
        if (StringUtils.isNoneBlank(vo.getCode400())) {
            List<ProfileDO> list = profileMapper.queryBy400Code(vo.getCode400(), vo.getUserId());
            if (!CollectionUtils.isEmpty(list)) {
                throw new AuthException(403, "该400账号已经绑定其他用户");
            }
        }
    }

    /**
     * 根据登录名修改用户信息<br>
     * 目前主要用于中铁建的会员注册流程，注册会员(添加工作空间)成功之后，同步完善用户信息
     *
     * @param profileVO 用户信息
     * @return 修改结果
     */
    public ErrorCode updateByAccount(ProfileVO profileVO) {
        if (null == profileVO || StringUtil.isNullOrSpace(profileVO.getLoginName())) {
            return ErrorCode.IllegalArument;
        }

        String userId = accountService.queryUserIdByAccount(profileVO.getLoginName());

        if (StringUtil.isNullOrSpace(userId)) {
            return ErrorCode.IllegalArument;
        }
        profileVO.setUserId(userId);

        return update(profileVO);
    }


    /**
     * 查询登录用户信息，并更新缓存
     *
     * @param userId String 用户ID
     * @return ProfileVO 用户信息
     */
    public ProfileVO queryLoginUser(String userId) {
        List<Integer> authIds;
        ProfileVO result;

        result = this.item(userId);
        if (null == result) {
            LogHelper.debug(userId + "用户信息不存在！");
            return null;
        }

//        authIds = scepterService.authCodesByUserId(userId);
//
//        int size = authIds.size();
//        result.setAuthIds(authIds);
//        authIds.toArray(new Integer[size]),
        ErrorCode cacheCode = userContextManager.cacheUser(userId, getUserCacheVO(result), null, result.getSpaceId());
        if (ErrorCode.Success != cacheCode) {
            LogHelper.error("缓存用户信息步骤异常", ErrorCode.FailedToCacheUserDate.getCode());
            return null;
        }
        return result;
    }

    /**
     * 封装用户缓存信息
     *
     * @param profileVO ProfileVO
     * @return UserCacheVO
     */
    public UserCacheVO getUserCacheVO(ProfileVO profileVO) {
        if (null == profileVO) {
            return new UserCacheVO();
        }
        UserCacheVO userCacheVO = new UserCacheVO();

        userCacheVO.setUserId(profileVO.getUserId());
        userCacheVO.setSpaceId(profileVO.getSpaceId());
        userCacheVO.setDeptId(profileVO.getDeptId());
        userCacheVO.setName(profileVO.getName());
        userCacheVO.setMobile(profileVO.getMobile());
        userCacheVO.setSapCode(profileVO.getSapCode());
        userCacheVO.setCode400(profileVO.getCode400());
        userCacheVO.setIsService(profileVO.getIsService());
        userCacheVO.setPurchaseGroup(profileVO.getPurchaseGroup());
        if (StringUtil.isNullOrEmpty(profileVO.getDeptId()) || AuthConstant.DEFAULT_PARENT_DEPT_ID.equals(profileVO.getDeptId())) {
            return userCacheVO;
        }
        DepartmentVO departmentVO = departmentService.item(profileVO.getDeptId());

        if (null == departmentVO) {
            return userCacheVO;
        }
        userCacheVO.setDeptName(departmentVO.getName());
        userCacheVO.setDeptCode(departmentVO.getCode());
        return userCacheVO;
    }

    /**
     * 查询部门下员工数量
     *
     * @param deptId String
     * @return Integer
     */
    public Integer queryListByDept(String deptId) {
        return profileMapper.queryCountByDept(deptId);
    }

    /**
     * 修改用户锁状态
     *
     * @param lockVO LockVO
     * @return ErrorCode
     */
    public ErrorCode updateLock(LockVO lockVO) {
        List<String> userIds = lockVO.getUserIds();

        for (String userId : userIds) {
            ProfileDO profileDO = new ProfileDO();
            profileDO.setUserId(userId);
            profileDO.setLocked(lockVO.getLock());
            profileMapper.update(profileDO);
        }
        return ErrorCode.Success;
    }


    /**
     * 用户信息封装方法
     *
     * @param profileVO ProfileVO
     * @return UserVO
     */
    private UserVO packageUserInfo(ProfileVO profileVO) {
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(profileVO, userVO);

        List<String> roleIds = new ArrayList<>();
        StringBuilder roleName = new StringBuilder();

        //封装账号信息
        AccountVO accountVO = accountService.queryAccountById(profileVO.getUserId());
        if (null != accountVO) {
            userVO.setLoginName(accountVO.getLoginName());
            userVO.setLastLoginTime(accountVO.getLastLoginTime());
        }

        if (!StringUtil.isNullOrEmpty(profileVO.getDeptId())) {
            //查询所属部门名称
            userVO.setDeptName(departmentService.queryFullDeptName(profileVO.getDeptId()));
        }
        //查询角色信息（用于展示）
        List<RoleVO> roleVOs = scepterService.getRolesByUserId(profileVO.getUserId());
        if (!StringUtil.isNullOrEmpty(profileVO.getDeptId())) {
            //查询所属部门名称
            userVO.setDeptName(departmentService.queryFullDeptName(profileVO.getDeptId()));
        }
        if (!StringUtil.isNullOrEmpty(profileVO.getJobId())) {
            JobDTO jobDTO = profileMapper.getJobNameByUserId(profileVO.getJobId());
            if (jobDTO != null) {
                userVO.setJobName(jobDTO.getName());
                userVO.setJobCode(jobDTO.getJobCode());
            }
        }


        for (RoleVO roleVO : roleVOs) {
            if (null == roleVO) {
                continue;
            }
            roleIds.add(roleVO.getId());
            roleName.append(roleVO.getName()).append(",");
        }


        if (0 < roleName.length()) {
            roleName.deleteCharAt(roleName.length() - 1);//去掉尾部多余的分隔符（逗号）
        }

        userVO.setRoleNames(roleName.toString());
        userVO.setRoleIds(roleIds);
        userVO.setRoleVOs(roleVOs);

        return userVO;
    }

    /**
     * 查询用户信息(Oauth2)
     *
     * @param userId String
     * @param userId String
     * @return ProfileVO
     */
    public UserVO getUserInfo(String appId, String userId) throws Exception {
        UserVO result = item(userId);
        if (result != null) {
            result.setOpenId(getOpenId(appId, userId));
        }
        return result;
    }

    /**
     * 生成OpenId
     *
     * @param appId
     * @param userId
     * @return
     * @throws Exception
     */
    private String getOpenId(String appId, String userId) throws Exception {
        String openIdMsg = "oauth_app_id=" + appId + "&user_id=" + userId;
        byte[] openIdByte = CryptoUtil.encryptMD5(openIdMsg.getBytes(StandardCharsets.UTF_8));
        return new BigInteger(openIdByte).toString(16);
    }

    /**
     * 查询用户的工作空间ID<br />
     * 从缓存中获取workspaceID，如果获取失败，则查询数据库获取用户workspaceId,同时更新缓存
     *
     * @param userId String
     * @return String
     */
    public ErrorCode queryWorkspaceId(String userId, Ref<String> spaceIdRef) {
        //获取缓存
        String spaceId = userContextManager.getWorkspaceId(userId);
        if (!StringUtil.isNullOrEmpty(spaceId)) {
            spaceIdRef.set(spaceId);
            return ErrorCode.Success;
        }

        //查询用户信息，并刷新缓存
        ProfileVO profileVO = queryLoginUser(userId);

        if (null == profileVO) {
            LogHelper.error("用户信息异常！", ErrorCode.NeedLogin.getCode());
            return ErrorCode.NeedLogin;
        }
        LogHelper.debug("获取用户缓存信息失效，更新缓存成功！");
        spaceIdRef.set(profileVO.getSpaceId());
        return ErrorCode.Success;
    }

    /**
     * 查询用户所属企业对应的权限模板ID
     *
     * @param userId        String
     * @param templateIdRef Ref<String>
     * @return ErrorCode
     */
    public ErrorCode queryAuthTemplateId(String userId, Ref<String> templateIdRef) {
        Ref<String> spaceIdRef = new Ref<>("");
        ErrorCode queryCode = queryWorkspaceId(userId, spaceIdRef);

        if (queryCode != ErrorCode.Success) {
            return queryCode;
        }

        WorkspaceVO workspaceVO = workspaceService.item(spaceIdRef.get());

        if (null == workspaceVO) {
            LogHelper.error("查询用户所属工作空间信息错误！", ErrorCode.FailedToRetreiveRecord.getCode());
            return ErrorCode.FailedToRetreiveRecord;
        }

        templateIdRef.set(workspaceVO.getTempId());
        return ErrorCode.Success;
    }


    @Transactional(rollbackFor = Exception.class)
    public ErrorCode addUserWithAccount(AccountPwdVO accountPwdVO, Ref<String> userIdRef) throws Exception {
        ProfileVO profileVO = new ProfileVO();
        profileVO.setSpaceId(AuthConstant.DEFAULT_WORKSPACE_ID);

        profileVO.setPassword(accountPwdVO.getPassword());
        profileVO.setLoginName(accountPwdVO.getLoginName());

        return insert(profileVO, userIdRef);
    }

    /**
     * 获取用户缓存信息
     *
     * @param userId String
     * @return String
     */
    public UserCacheVO getUserCache(String userId) {
        UserCacheVO obj = (UserCacheVO) userContextManager.getUserData(userId);
        if (null != obj) {
            userContextManager.renewLeaseSession(userId);
            LogHelper.debug("获取用户缓存信息操作成功，刷新缓存！");
            return obj;
        }
        //缓存数据失效，重新查询用户信息，并添加到缓存数据库
        ProfileVO profileVO = queryLoginUser(userId);
        return getUserCacheVO(profileVO);
    }

    public ErrorCode checkExistMobile(String mobile, String userId) {
        if (StringUtils.isNotBlank(mobile)) {
            ProfileDO profileDO = new ProfileDO();
            profileDO.setMobile(mobile);
            profileDO.setUserId(userId);
            int count = profileMapper.getCountByMobile(profileDO);
            if (count > 0) {
                return ErrorCode.MobileExistError;
            }
        }
        return ErrorCode.Success;
    }

    public ErrorCode checkExistName(String name, String spaceId, String userId) {
        if (StringUtils.isNotBlank(name)) {
            ProfileDO profileDO = new ProfileDO();
            profileDO.setName(name);
            profileDO.setUserId(userId);
            profileDO.setSpaceId(spaceId);
            int count = profileMapper.getCountByName(profileDO);
            if (count > 0) {
                return ErrorCode.NameExistError;
            }
        }
        return ErrorCode.Success;
    }

    @Transactional
    public ErrorCode regMember(RegMemberVO regMemberVO) {
        WorkspaceVO workspaceVO = new WorkspaceVO();
        workspaceVO.setId(regMemberVO.getWorkSpaceId());
        workspaceVO.setSite(regMemberVO.getSite());
        workspaceVO.setName(regMemberVO.getWorkSpaceId());
        workspaceVO.setTempId(String.valueOf(regMemberVO.getType()));
        workspaceVO.setAccount(regMemberVO.getLoginName());
        workspaceVO.setPassword(regMemberVO.getPassword());
        workspaceVO.setType(String.valueOf(regMemberVO.getType()));
        ErrorCode errorCode;
        try {
            errorCode = workspaceService.insert(workspaceVO);
            if (errorCode.getCode() != ErrorCode.Success.getCode()) {
                throw new AuthException(ErrorCode.FailedToInsertRecord);
            }
        } catch (Exception e) {
            throw new AuthException(ErrorCode.FailedToInsertRecord);
        }

        ProfileVO profileVO = new ProfileVO();
        profileVO.setLoginName(regMemberVO.getLoginName());
        profileVO.setName(regMemberVO.getName());
        profileVO.setIdNumber(regMemberVO.getIdNumber());
        profileVO.setMobile(regMemberVO.getMobile());
        errorCode = updateByAccount(profileVO);
        if (errorCode.getCode() != ErrorCode.Success.getCode()) {
            throw new AuthException(errorCode);
        }

        return errorCode;
    }

    public List<String> getMobilesByDepts(String workSpaceId, List<String> deptIds) {
        if (StringUtils.isEmpty(workSpaceId) && CollectionUtils.isEmpty(deptIds)) {
            return Collections.EMPTY_LIST;
        }
        List<String> mobiles = profileMapper.getMobilesByWorkSpaceDept(workSpaceId, deptIds);
        return mobiles;
    }

    public ErrorCode queryBy400Code(String code400, Ref<String> userIdRef) {
        if (StringUtils.isBlank(code400)) {
            throw new AuthException(403, "参数异常，400账户为空");
        }
        List<ProfileDO> list = profileMapper.queryBy400Code(code400, null);
        if (!CollectionUtils.isEmpty(list) && list.size() == 1) {
            userIdRef.set(list.get(0).getUserId());
            return ErrorCode.Success;
        }
        throw new AuthException(403, "该400账号未绑定无法登陆");
    }

    public ProfileVO getUserInfoByName(String username) {
        AccountPwdVO accountPwdVO = accountService.getAccountByName(username);
        if (accountPwdVO == null) {
            return null;
        }
        ProfileDO profileDO = profileMapper.selectById(accountPwdVO.getUserId());
        ProfileVO profileVO = getVO(profileDO);
        if (profileVO == null) {
            return null;
        }
        profileVO.setLoginName(username);
        profileVO.setPassword(accountPwdVO.getPassword());
        profileVO.setUserId(accountPwdVO.getUserId());
        return profileVO;
    }

    public String getUserIdByErpCode(String erpCode) throws Exception {
        String userId = profileMapper.getUserIdByErpCode(erpCode);
        if (StringUtils.isEmpty(userId)) {
            throw new AuthException("用户信息不存在");
        }
        return userId;
    }

    public ErrorCode setUserJobId(ProfileVO profileVO) {
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String format = formatter.format(date);
        if (profileVO.getType() != null) {
            String jobId = profileMapper.getJobById(profileVO.getJobId());
            if (profileVO.getType() == 1) {
                UserVO item = this.item(profileVO.getUserId());
                if (item != null) {
                    /**员工设置岗位*/
                    profileMapper.setUserJobId(jobId, profileVO.getUserId());
                    if (!StringUtil.isNullOrEmpty(jobId)) {
                        Integer userType = 1;
                        String jobUserId = profileMapper.getJobUserById(profileVO.getUserId(), userType);
                        if (!StringUtil.isNullOrEmpty(jobUserId)) {
                            profileMapper.updateJobUser(jobId, profileVO.getUserId(), format);
                        } else {
                            String id = String.valueOf(snowflake());
                            profileMapper.createJobUser(id, jobId, profileVO.getUserId(), userType, format);
                        }
                    } else {
                        return ErrorCode.JOBNULL;
                    }
                } else {
                    throw new AuthException("未找到用户类型，请联系管理员");
                }
            } else if (profileVO.getType() == 2) {
                TechnicianVO technicianVO = profileMapper.getTechnician(profileVO.getUserId());
                if (technicianVO != null) {
                    /**技师设置岗位*/
                    profileMapper.setTechnicianJobId(jobId, profileVO.getUserId());
                    if (!StringUtil.isNullOrEmpty(jobId)) {
                        Integer userType = 2;
                        String jobUserId = profileMapper.getJobUserById(profileVO.getUserId(), userType);
                        if (!StringUtil.isNullOrEmpty(jobUserId)) {
                            profileMapper.updateJobUser(jobId, profileVO.getUserId(), format);
                        } else {
                            String id = String.valueOf(snowflake());
                            profileMapper.createJobUser(id, jobId, profileVO.getUserId(), userType, format);
                        }
                    } else {
                        return ErrorCode.JOBNULL;
                    }
                } else {
                    throw new AuthException("技师信息不存在，请联系管理员");
                }
            }
        } else {
            throw new AuthException("用户信息不存在");
        }
        return ErrorCode.Success;
    }

    public static long snowflake() {
        Snowflake snowflake = IdUtil.getSnowflake(1, 1);
        long id = snowflake.nextId();
        return id;
    }

    public ErrorCode updateForWx(ProfileVO profileVO) {
        UserVO item = this.item(profileVO.getUserId());
        if (item != null) {
            ProfileDO profileDO = new ProfileDO();
            BeanUtils.copyProperties(profileVO, profileDO);
            profileMapper.update(profileDO);
        } else {
            throw new AuthException("用户信息不存在");
        }
        return ErrorCode.Success;
    }

    public ErrorCode updateUserAvatorForWx(ProfileVO profileVO) {
        UserVO item = this.item(profileVO.getUserId());
        if (item != null) {
            profileMapper.updateUserAvatorForWx(profileVO.getUserId(), profileVO.getImgUrl());
        } else {
            throw new AuthException("用户信息不存在");
        }
        return ErrorCode.Success;
    }

    public List<UserScore> getUserScore(String userId) {
        List<UserScore> userScores = profileMapper.getUserScoreById(userId);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (UserScore userScore : userScores) {
            if (userScore.getCreateTime() != null) {
                userScore.setCreateTimeName(dateFormat.format(userScore.getCreateTime()));
            }
        }
        return userScores;
    }

    public PageCommonVO getUserScoreV1(SearchCommonVO<UserScoreVO> condition, String userId) {
        PageCommonVO<UserScore> pageCommonVO = new PageCommonVO<>();
//        PageHelperPlus.orderBy(COMM_ORDER_BY);
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<UserScore> doList = profileMapper.getUserScoreById(condition.getFilters().getId());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (UserScore userScore : doList) {
            if (userScore.getCreateTime() != null) {
                userScore.setCreateTimeName(dateFormat.format(userScore.getCreateTime()));
            }
        }
//        List<UserScore> voList = getVOList(doList);
        pageCommonVO.setPageInfo(new PageInfo<UserScore>(doList));
        pageCommonVO.setPageInfoList(doList);
        return pageCommonVO;
    }
}
